from pyeasyaccept.commom.PythonEasyAcceptTestRunner import PythonEasyAcceptTestRunner
from pyeasyaccept.result.ResultsHandler import ResultsHandler
import os
import sys

""" 
This class is the Python EasyAccept Facade. With this facade, the user can submit tests to be executed
and get its results in many ways.

@author: Gustavo Pereira
"""
class PythonEasyAcceptFacade:

    def __init__(self, facade, tests):
        
        if(not self.isValidFacade(facade)):
            raise Exception("'None' is not a valid Facade.")
        
        self.pythonApplicationFacade = facade
        self.tests = tests
        self.resultHandler = ResultsHandler()
        self.errorListeners = []
        self.numberErrorsToReport = sys.maxint
    
    def isValidFacade(self, facade):
        return facade != None
            
    def executeTests(self):
        """ 
        Execute the acceptance tests, driven from each one of the test script files.
        """     
        if(len(self.tests) == 0):
            raise Exception("There is not test script to be executed.")
            
        
        inexistentFiles = self.__getInexistentFiles()
        if(len(inexistentFiles) > 0):
            self.__raiseInexistentFileException(inexistentFiles)
        for test in self.tests:
            self.runAcceptanceTests(test)
                             

    def runAcceptanceTests(self, test):
        """
        Run the acceptante tests
        @param test: a test script 
        """
        runner = PythonEasyAcceptTestRunner(self.pythonApplicationFacade, test)
        runner.setNumberErrorsToReport(self.numberErrorsToReport)
        scriptResultManager = runner.runScript(self.errorListeners)
        self.resultHandler.addResult(scriptResultManager)

    def addErrorListener(self, listener):
        """
        Adds a PyEAErrorListener to observe errors in test scripts.
        Whenever an error occurs in a test script, this listener will receive an event reporting the error occurred.
        @param listener: the PyEAErrorListener to be added.  
        """
        self.errorListeners.append(listener)
    
    def __getInexistentFiles(self):
        
        inexistentFiles = []
        for file in self.tests:
            if( not(os.path.exists(file)) ):
                inexistentFiles.append(file)
        
        return inexistentFiles
        
    def __raiseInexistentFileException(self, inexistentFiles):
        message = "Can not execute tests. Inexistent file(s): "
        for file in inexistentFiles:
            message += "[" + file + "]"
        raise Exception(message)

#= = = = = = = = = = = = = = = general results = = = = = = = = = = = = = = = = = = = = =

    def getSummarizedResults(self):
        """
        This method returns the Summarized results of all executed tests.
        Summarized results contains: Tested scripts name, Number of passed tests and
        Number of Not passed tests.
        @return: the Summarized test results
        """
        return self.resultHandler.getSummarizedResults()
    
    def getCompleteResults(self):
        """
        This method returns the complete results of all executed tests.
        Complete results contains: Tested scripts name, Number of passed tests,
        Number of Not passed tests and Erros descriptions (if it has been occurred).
        @return: the complete test results
        """
        return self.resultHandler.getCompleteResults()
    
    def getTotalNumberOfPassedTests(self):
        """
        This method returns the total number of passed tests
        @return: the total number of passed tests
        """
        return self.resultHandler.getTotalNumberOfPassedTests()
    
    def getTotalNumberOfNotPassedTests(self):
        """
        This method returns the total number of Not passed tests
        @return: the total number of Not passed tests
        """
        return self.resultHandler.getTotalNumberOfNotPassedTests()
    
    def getTotalNumberOfTests(self):
        """
        This method returns the total number of executed tests
        @return: the total number of executed tests
        """
        return self.resultHandler.getTotalNumTests()
    
    def getTestLineResult(self, file, line):
        """
        This method returns a Result object for a specified script line.
        @param file: the test script
        @param line: the test script line
        @return: the test result for a specified script line, or None if
                the referred line does not exist
        """
        return self.resultHandler.getTestLineResult(file, line)
    
    def maxErrorsToReport(self, numberErrorsToReport):
        """
        This method sets the number of errors that can be at the script.
        @param numberErrorsToReport: number of errors that can be at the script.  
        """
#        self.errorsToReport = True
        self.numberErrorsToReport = numberErrorsToReport
        
#= = = = = = = = = = = = = = = each script results= = = = = = = = = = = = = = = = = = = = =

    def getScriptCompleteResults(self, scriptName):
        """
        This method returns the complete results of a specified test script.
        Complete result contains: Tested script name, Number of passed tests,
        Number of Not passed tests and Erros descriptions (if it has been occurred).
        @param scriptName: the test script
        @return: the complete test result or None if
                the refered script does not exist
        """
        return self.resultHandler.getScriptCompleteResults(scriptName)

    def getScriptSummarizedResults(self, scriptName):
        """
        This method returns the Summarized results of a specificied test script
        Summarized result contains: Tested script name, Number of passed tests,
        and Number of Not passed tests.
        @param scriptName: the test script
        @return: the summarized test result or None if
                the refered script does not exist
        """
        return self.resultHandler.getScriptSummarizedResults(scriptName)

    def getScriptNumberOfPassedTests(self, scriptName):
        """
        This method returns the number of passed tests of a specified test script.
        @param scriptName: the test script
        @return: the number of passed tests, or None if
                the refered script does not exist
        """
        return self.resultHandler.getScriptNumberOfPassedTests(scriptName)
    
    def getScriptNumberOfNotPassedTests(self, scriptName):
        """
        This method returns the number of Not passed tests of a specified test script.
        @param scriptName: the test script
        @return: the number of Not passed tests, or None if
                the refered script does not exist
        """
        return self.resultHandler.getScriptNumberOfNotPassedTests(scriptName)
    
    def getScriptTotalNumberOfTests(self, scriptName):
        """
        This method returns the total number of executed tests of a specified test script.
        @param scriptName: the test script
        @return: the total number of executed tests of a specified test script, or None if
                the refered script does not exist
        """
        return self.resultHandler.getScriptTotalNumberOfTests(scriptName)
    
    def getScriptResults(self, scriptName):
        """
        This method returns the set of all of the specified test script Result objects.
        @return: all the test results of the specified test script, or None if
                the refered script does not exist
        """
        return self.resultHandler.getScriptResults(scriptName)
    